﻿package org.hvilela {
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;		

	/**
	 * @author hvilela
	 * http://hvilela.com/
	 */
	public class Sphere extends Sprite {
		
		private var radius:uint;
		private var speed:Number;
		private var minAlpha:Number;
		private var maxAlpha:Number;

		private var itens:Array;

		public function Sphere(radius:uint = 130, speed:Number = 0.5, minAlpha:Number = 0.5, maxAlpha:Number = 1) {
			this.radius = radius;
			this.speed = speed;
			this.minAlpha = minAlpha;
			this.maxAlpha = maxAlpha;

			itens = new Array();

			addEventListener(Event.ADDED, onAdd);
			addEventListener(Event.REMOVED, onRemove);
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}

		private function onAdd(event : Event) : void {
			if (event.target != this) {
				itens.push(event.target);				
				distribute();
			}
		}

		private function onRemove(event : Event) : void {
			if (event.target != this) {
				itens.splice(itens.indexOf(event.target), 1);	
				distribute();
			}
		}

		private function distribute(event : Event = null) : void {		
			for (var i : uint = 0; i < itens.length; i++) {
				var object : DisplayObject = itens[i] as DisplayObject;

				var phi : Number = Math.acos(-1 + (2 * i - 1) / itens.length);
				var theta : Number = Math.sqrt(numChildren * Math.PI) * phi;

				object.x = radius * Math.cos(theta) * Math.sin(phi);
				object.y = radius * Math.sin(theta) * Math.sin(phi);
				object.z = radius * Math.cos(phi);
			}
		}

		private function onEnterFrame( event : Event ) : void {
			var a:Number = (-Math.min(Math.max(mouseY, -250), 250) / 2000 ) * speed;
			var b:Number = (Math.min(Math.max(mouseX, -250), 250) / 2000 ) * speed;
			var c:Number = 0;

			var sa:Number = Math.sin(a);
			var ca:Number = Math.cos(a);
			var sb:Number = Math.sin(b);
			var cb:Number = Math.cos(b);
			var sc:Number = Math.sin(c);
			var cc:Number = Math.cos(c);

			for (var i : uint = 0; i < itens.length; i++) {
				var object : DisplayObject = itens[i] as DisplayObject;

				var rx1 : Number = object.x;
				var ry1 : Number = object.y * ca + object.z * -sa;
				var rz1 : Number = object.y * sa + object.z * ca;

				var rx2 : Number = rx1 * cb + rz1 * sb;
				var ry2 : Number = ry1;
				var rz2 : Number = rx1 * -sb + rz1 * cb;

				var rx3 : Number = rx2 * cc + ry2 * -sc;
				var ry3 : Number = rx2 * sc + ry2 * cc;
				var rz3 : Number = rz2;

				object.x = rx3;
				object.y = ry3;
				object.z = rz3;
				
				object.alpha = (1 - object.z / radius) / 2 * (maxAlpha - minAlpha) + minAlpha;
			}

			itens.sortOn("z", Array.DESCENDING | Array.NUMERIC);
			for (var i : uint = 0; i < itens.length; i++ ) {
				setChildIndex(itens[i], i);
			}				
		}
	}
}